This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
dates <- ymd('2020-01-01') + weeks(0:53)
countries <- unlist(countries_per_continent) %>% sort()
base_df <- tibble(
date = rep(dates, rep(length(countries), length(dates))),
location = rep(countries, length(dates))
) %>%
filter(year(date) == 2020) %>%
mutate(week = week(date)) %>%
select(week, location) %>%
left_join(covid_data %>% select(location, continent, population) %>% distinct(),
by = 'location') %>%
drop_na()
df <- covid_data %>%
filter(lubridate::year(date) == 2020) %>%
replace_na(list(new_cases = 0,
new_deaths = 0,
new_tests = 0)) %>%
group_by(week = week(date),
location, continent, population) %>%
summarise(new_cases = sum(new_cases),
positive_rate = round(sum(new_cases) / sum(new_tests), 2),
new_deaths = sum(new_deaths),
.groups = 'drop')
evolution <- base_df %>%
left_join(df, by = c('week', 'location')) %>%
select(week,
location,
continent = continent.x,
population = population.x,
new_cases,
positive_rate,
new_deaths) %>%
replace_na(list(new_cases = 0,
positive_rate = 0,
new_deaths = 0)) %>%
group_by(location, continent, population) %>%
mutate(positive_rate = if_else(is.infinite(positive_rate), 0, positive_rate),
total_deaths = slide_dbl(new_deaths, sum, .before = Inf, .after = 0, .complete = FALSE),
total_cases = slide_dbl(new_cases, sum,.before = Inf, .after = 0, .complete = FALSE),
cases_pm = round(total_cases / population * 1e+6),
deaths_pm = round(total_deaths / population * 1e+6)) %>%
ungroup()
evolution %>%
plot_ly(x = ~ deaths_pm,
y = ~ cases_pm,
color = ~ continent,
size = ~ population,
hoverinfo = 'text',
text = ~ location) %>%
add_text(x = 45,
y = 500,
text = ~ paste0('week: ', week),
frame = ~ week,
textfont = list(size = 150,
color = toRGB('gray80'),
opacity = .5),
showlegend = FALSE) %>%
add_markers(frame = ~ week,
ids = ~ location,
marker = list(showmode = 'diameter',
showref = 0.9)) %>%
layout(xaxis = list(type = 'log',
range = c(0, 3.25),
title = 'Total Deaths per Million'),
yaxis = list(title = 'Total Cases per Million',
type = 'log',
range = c(0, 5.1)),
title = 'Total Cases & Total Deaths per Million') %>%
animation_opts(frame = 500,
transition = 500) %>%
animation_slider(hide = TRUE)
week_new_cases <- evolution %>%
select(week, location, new_cases) %>%
mutate(new_cases_week = paste0('new_cases_week_', week)) %>%
select(- week) %>%
spread(new_cases_week, new_cases, fill = 0) %>%
arrange(location)
week_positive_rate <- evolution %>%
select(week, location, positive_rate) %>%
mutate(positive_rate_week = paste0('positive_rate_week_', week)) %>%
select(- week) %>%
spread(positive_rate_week, positive_rate, fill = 0) %>%
arrange(location)
week_new_deaths <- evolution %>%
select(week, location, new_deaths) %>%
mutate(new_deaths_week = paste0('new_deaths_week_', week)) %>%
select(- week) %>%
spread(new_deaths_week, new_deaths, fill = 0) %>%
arrange(location)
cd_tidy <- week_new_cases %>%
bind_cols(week_positive_rate %>% select(-location)) %>%
bind_cols(week_new_deaths %>% select(-location))
cd_tidy
require(embed)
Loading required package: embed
Loading required package: recipes
Attaching package: 㤼㸱recipes㤼㸲
The following object is masked from 㤼㸱package:stringr㤼㸲:
fixed
The following object is masked from 㤼㸱package:stats㤼㸲:
step
require(tidymodels)
Loading required package: tidymodels
-- Attaching packages ---------------------------------------------------------- tidymodels 0.1.2 --
v broom 0.7.5 v rsample 0.0.9
v dials 0.0.9 v tune 0.1.3
v infer 0.5.4 v workflows 0.2.2
v modeldata 0.1.0 v yardstick 0.0.7
v parsnip 0.1.5
-- Conflicts ------------------------------------------------------------- tidymodels_conflicts() --
x scales::discard() masks purrr::discard()
x magrittr::extract() masks tidyr::extract()
x plotly::filter() masks dplyr::filter(), stats::filter()
x recipes::fixed() masks stringr::fixed()
x dplyr::lag() masks stats::lag()
x magrittr::set_names() masks purrr::set_names()
x yardstick::spec() masks readr::spec()
x recipes::step() masks stats::step()
cd_recipe <- recipe(~., data = cd_tidy) %>%
update_role(location, new_role = 'id') %>%
step_zv(all_numeric()) %>%
#step_normalize(all_predictors()) %>%
step_umap(all_predictors())
cd_prep <- prep(cd_recipe)
cd_bake <- bake(cd_prep, new_data = NULL)
country_info <- covid_data %>%
select(location, continent, population) %>%
distinct() %>%
arrange(location)
cd_final <- cd_bake %>%
left_join(country_info, by = 'location')
require(highcharter)
Loading required package: highcharter
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
Highcharts (www.highcharts.com) is a Highsoft software product which is
not free for commercial and Governmental use
withinss <- tibble(
center = 1:15,
soq = map_dbl(1:15, ~ kmeans(cd_final %>% select(umap_1, umap_1), centers = .x)$tot.withinss)
)
hchart(withinss, 'line', hcaes(x = center, y = soq))
clusters <- kmeans(cd_final %>% select(umap_1, umap_2), centers = 4)
cd_final %<>%
mutate(cluster = paste0('cluster_', clusters$cluster))
cd_final %>%
plot_ly(x = ~ umap_1,
y = ~ umap_2,
color = ~ cluster) %>%
add_markers(hoverinfo = 'text',
text = ~ location,
symbol = ~ continent)
cd_final %>%
hchart('scatter',
hcaes(x = umap_1,
y = umap_2,
group = continent,
color = cluster,
size = population / max(population)),
showInLegend = FALSE) %>%
hc_yAxis(
title = list(text = "y Axis at right"),
opposite = TRUE,
alternateGridColor = "#FAFAFA",
minorTickInterval = "auto",
minorGridLineDashStyle = "LongDashDotDot",
showFirstLabel = TRUE,
showLastLabel = TRUE
)
NA
NA
NA
flights %>%
transmute(week = as.Date(cut(time_hour, "week")), dep_delay, origin) %>%
group_by(origin, week) %>%
summarise(dep_delay = sum(dep_delay, na.rm = TRUE)) %>%
e_charts(x = week) %>%
e_datazoom(type = 'slider',
toolbox = FALSE,
bottom = -5) %>%
e_tooltip() %>%
e_title('Departure delays by airport') %>%
e_x_axis(week, axisPointer = list(show = TRUE)) %>%
e_line(dep_delay)
`summarise()` has grouped output by 'origin'. You can override using the `.groups` argument.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KYGBge3IgZXZhbD1GQUxTRX0NCmRhdGVzIDwtIHltZCgnMjAyMC0wMS0wMScpICsgd2Vla3MoMDo1MykNCmNvdW50cmllcyA8LSB1bmxpc3QoY291bnRyaWVzX3Blcl9jb250aW5lbnQpICU+JSBzb3J0KCkNCg0KYmFzZV9kZiA8LSB0aWJibGUoDQogICAgZGF0ZSA9IHJlcChkYXRlcywgcmVwKGxlbmd0aChjb3VudHJpZXMpLCBsZW5ndGgoZGF0ZXMpKSksDQogICAgbG9jYXRpb24gPSByZXAoY291bnRyaWVzLCBsZW5ndGgoZGF0ZXMpKQ0KKSAlPiUNCiAgICBmaWx0ZXIoeWVhcihkYXRlKSA9PSAyMDIwKSAlPiUNCiAgICBtdXRhdGUod2VlayA9IHdlZWsoZGF0ZSkpICU+JQ0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbikgJT4lDQogICAgbGVmdF9qb2luKGNvdmlkX2RhdGEgJT4lIHNlbGVjdChsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUgZGlzdGluY3QoKSwNCiAgICAgICAgICAgICAgYnkgPSAnbG9jYXRpb24nKSAlPiUNCiAgICBkcm9wX25hKCkNCg0KZGYgPC0gY292aWRfZGF0YSAlPiUNCiAgICBmaWx0ZXIobHVicmlkYXRlOjp5ZWFyKGRhdGUpID09IDIwMjApICU+JQ0KICAgIHJlcGxhY2VfbmEobGlzdChuZXdfY2FzZXMgPSAwLA0KICAgICAgICAgICAgICAgICAgICBuZXdfZGVhdGhzID0gMCwNCiAgICAgICAgICAgICAgICAgICAgbmV3X3Rlc3RzID0gMCkpICU+JQ0KICAgIGdyb3VwX2J5KHdlZWsgPSB3ZWVrKGRhdGUpLA0KICAgICAgICAgICAgIGxvY2F0aW9uLCBjb250aW5lbnQsIHBvcHVsYXRpb24pICU+JQ0KICAgIHN1bW1hcmlzZShuZXdfY2FzZXMgPSBzdW0obmV3X2Nhc2VzKSwNCiAgICAgICAgICAgICAgcG9zaXRpdmVfcmF0ZSA9IHJvdW5kKHN1bShuZXdfY2FzZXMpIC8gc3VtKG5ld190ZXN0cyksIDIpLA0KICAgICAgICAgICAgICBuZXdfZGVhdGhzID0gc3VtKG5ld19kZWF0aHMpLA0KICAgICAgICAgICAgICAuZ3JvdXBzID0gJ2Ryb3AnKQ0KDQpldm9sdXRpb24gPC0gYmFzZV9kZiAlPiUNCiAgICBsZWZ0X2pvaW4oZGYsIGJ5ID0gYygnd2VlaycsICdsb2NhdGlvbicpKSAlPiUNCiAgICBzZWxlY3Qod2VlaywNCiAgICAgICAgICAgbG9jYXRpb24sDQogICAgICAgICAgIGNvbnRpbmVudCA9IGNvbnRpbmVudC54LA0KICAgICAgICAgICBwb3B1bGF0aW9uID0gcG9wdWxhdGlvbi54LA0KICAgICAgICAgICBuZXdfY2FzZXMsDQogICAgICAgICAgIHBvc2l0aXZlX3JhdGUsDQogICAgICAgICAgIG5ld19kZWF0aHMpICU+JQ0KICAgIHJlcGxhY2VfbmEobGlzdChuZXdfY2FzZXMgPSAwLA0KICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZV9yYXRlID0gMCwNCiAgICAgICAgICAgICAgICAgICAgbmV3X2RlYXRocyA9IDApKSAlPiUNCiAgICBncm91cF9ieShsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUNCiAgICBtdXRhdGUocG9zaXRpdmVfcmF0ZSA9IGlmX2Vsc2UoaXMuaW5maW5pdGUocG9zaXRpdmVfcmF0ZSksIDAsIHBvc2l0aXZlX3JhdGUpLA0KICAgICAgICAgICB0b3RhbF9kZWF0aHMgPSBzbGlkZV9kYmwobmV3X2RlYXRocywgc3VtLCAuYmVmb3JlID0gSW5mLCAuYWZ0ZXIgPSAwLCAuY29tcGxldGUgPSBGQUxTRSksDQogICAgICAgICAgIHRvdGFsX2Nhc2VzID0gc2xpZGVfZGJsKG5ld19jYXNlcywgc3VtLC5iZWZvcmUgPSBJbmYsIC5hZnRlciA9IDAsIC5jb21wbGV0ZSA9IEZBTFNFKSwNCiAgICAgICAgICAgY2FzZXNfcG0gPSByb3VuZCh0b3RhbF9jYXNlcyAvIHBvcHVsYXRpb24gKiAxZSs2KSwNCiAgICAgICAgICAgZGVhdGhzX3BtID0gcm91bmQodG90YWxfZGVhdGhzIC8gcG9wdWxhdGlvbiAqIDFlKzYpKSAlPiUgDQogICAgdW5ncm91cCgpDQoNCg0KDQpldm9sdXRpb24gJT4lDQogICAgcGxvdF9seSh4ICAgICAgICAgPSB+IGRlYXRoc19wbSwNCiAgICAgICAgICAgIHkgICAgICAgICA9IH4gY2FzZXNfcG0sDQogICAgICAgICAgICBjb2xvciAgICAgPSB+IGNvbnRpbmVudCwNCiAgICAgICAgICAgIHNpemUgICAgICA9IH4gcG9wdWxhdGlvbiwNCiAgICAgICAgICAgIGhvdmVyaW5mbyA9ICd0ZXh0JywNCiAgICAgICAgICAgIHRleHQgICAgICA9IH4gbG9jYXRpb24pICU+JQ0KICAgIGFkZF90ZXh0KHggPSA0NSwNCiAgICAgICAgICAgICB5ID0gNTAwLA0KICAgICAgICAgICAgIHRleHQgPSB+IHBhc3RlMCgnd2VlazogJywgd2VlayksDQogICAgICAgICAgICAgZnJhbWUgPSB+IHdlZWssDQogICAgICAgICAgICAgdGV4dGZvbnQgPSBsaXN0KHNpemUgPSAxNTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gdG9SR0IoJ2dyYXk4MCcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gLjUpLA0KICAgICAgICAgICAgIHNob3dsZWdlbmQgPSBGQUxTRSkgJT4lDQogICAgYWRkX21hcmtlcnMoZnJhbWUgID0gfiB3ZWVrLA0KICAgICAgICAgICAgICAgIGlkcyAgICA9IH4gbG9jYXRpb24sDQogICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChzaG93bW9kZSA9ICdkaWFtZXRlcicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93cmVmID0gMC45KSkgJT4lDQogICAgbGF5b3V0KHhheGlzID0gbGlzdCh0eXBlID0gJ2xvZycsDQogICAgICAgICAgICAgICAgICAgICAgICByYW5nZSA9IGMoMCwgMy4yNSksDQogICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9ICdUb3RhbCBEZWF0aHMgcGVyIE1pbGxpb24nKSwNCiAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ1RvdGFsIENhc2VzIHBlciBNaWxsaW9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnbG9nJywNCiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlID0gYygwLCA1LjEpKSwNCiAgICAgICAgICAgdGl0bGUgPSAnVG90YWwgQ2FzZXMgJiBUb3RhbCBEZWF0aHMgcGVyIE1pbGxpb24nKSAlPiUNCiAgICBhbmltYXRpb25fb3B0cyhmcmFtZSAgICAgID0gNTAwLA0KICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24gPSA1MDApICU+JQ0KICAgIGFuaW1hdGlvbl9zbGlkZXIoaGlkZSA9IFRSVUUpDQoNCmBgYA0KDQpgYGB7cn0NCndlZWtfbmV3X2Nhc2VzIDwtIGV2b2x1dGlvbiAlPiUgDQogICAgc2VsZWN0KHdlZWssIGxvY2F0aW9uLCBuZXdfY2FzZXMpICU+JSANCiAgICBtdXRhdGUobmV3X2Nhc2VzX3dlZWsgPSBwYXN0ZTAoJ25ld19jYXNlc193ZWVrXycsIHdlZWspKSAlPiUgDQogICAgc2VsZWN0KC0gd2VlaykgJT4lIA0KICAgIHNwcmVhZChuZXdfY2FzZXNfd2VlaywgbmV3X2Nhc2VzLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCndlZWtfcG9zaXRpdmVfcmF0ZSA8LSBldm9sdXRpb24gJT4lIA0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbiwgcG9zaXRpdmVfcmF0ZSkgJT4lIA0KICAgIG11dGF0ZShwb3NpdGl2ZV9yYXRlX3dlZWsgPSBwYXN0ZTAoJ3Bvc2l0aXZlX3JhdGVfd2Vla18nLCB3ZWVrKSkgJT4lIA0KICAgIHNlbGVjdCgtIHdlZWspICU+JSANCiAgICBzcHJlYWQocG9zaXRpdmVfcmF0ZV93ZWVrLCBwb3NpdGl2ZV9yYXRlLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCndlZWtfbmV3X2RlYXRocyA8LSBldm9sdXRpb24gJT4lIA0KICAgIHNlbGVjdCh3ZWVrLCBsb2NhdGlvbiwgbmV3X2RlYXRocykgJT4lIA0KICAgIG11dGF0ZShuZXdfZGVhdGhzX3dlZWsgPSBwYXN0ZTAoJ25ld19kZWF0aHNfd2Vla18nLCB3ZWVrKSkgJT4lIA0KICAgIHNlbGVjdCgtIHdlZWspICU+JSANCiAgICBzcHJlYWQobmV3X2RlYXRoc193ZWVrLCBuZXdfZGVhdGhzLCBmaWxsID0gMCkgJT4lIA0KICAgIGFycmFuZ2UobG9jYXRpb24pDQoNCg0KY2RfdGlkeSA8LSB3ZWVrX25ld19jYXNlcyAlPiUgDQogICAgYmluZF9jb2xzKHdlZWtfcG9zaXRpdmVfcmF0ZSAlPiUgc2VsZWN0KC1sb2NhdGlvbikpICU+JSANCiAgICBiaW5kX2NvbHMod2Vla19uZXdfZGVhdGhzICU+JSBzZWxlY3QoLWxvY2F0aW9uKSkNCg0KY2RfdGlkeQ0KYGBgDQoNCmBgYHtyfQ0KcmVxdWlyZShlbWJlZCkNCnJlcXVpcmUodGlkeW1vZGVscykNCg0KY2RfcmVjaXBlIDwtIHJlY2lwZSh+LiwgZGF0YSA9IGNkX3RpZHkpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKGxvY2F0aW9uLCBuZXdfcm9sZSA9ICdpZCcpICU+JSANCiAgICBzdGVwX3p2KGFsbF9udW1lcmljKCkpICU+JSANCiAgICAjc3RlcF9ub3JtYWxpemUoYWxsX3ByZWRpY3RvcnMoKSkgJT4lIA0KICAgIHN0ZXBfdW1hcChhbGxfcHJlZGljdG9ycygpKQ0KDQpjZF9wcmVwIDwtIHByZXAoY2RfcmVjaXBlKQ0KDQpjZF9iYWtlIDwtIGJha2UoY2RfcHJlcCwgbmV3X2RhdGEgPSBOVUxMKQ0KDQoNCg0KY291bnRyeV9pbmZvIDwtIGNvdmlkX2RhdGEgJT4lIA0KICAgIHNlbGVjdChsb2NhdGlvbiwgY29udGluZW50LCBwb3B1bGF0aW9uKSAlPiUgDQogICAgZGlzdGluY3QoKSAlPiUgDQogICAgYXJyYW5nZShsb2NhdGlvbikNCiAgICANCg0KY2RfZmluYWwgPC0gY2RfYmFrZSAlPiUgDQogICAgbGVmdF9qb2luKGNvdW50cnlfaW5mbywgYnkgPSAnbG9jYXRpb24nKQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KcmVxdWlyZShoaWdoY2hhcnRlcikNCg0KDQp3aXRoaW5zcyA8LSB0aWJibGUoDQogIGNlbnRlciA9IDE6MTUsDQogIHNvcSA9IG1hcF9kYmwoMToxNSwgfiBrbWVhbnMoY2RfZmluYWwgJT4lIHNlbGVjdCh1bWFwXzEsIHVtYXBfMSksIGNlbnRlcnMgPSAueCkkdG90LndpdGhpbnNzKQ0KKQ0KDQpoY2hhcnQod2l0aGluc3MsICdsaW5lJywgaGNhZXMoeCA9IGNlbnRlciwgeSA9IHNvcSkpDQoNCg0KY2x1c3RlcnMgPC0ga21lYW5zKGNkX2ZpbmFsICU+JSBzZWxlY3QodW1hcF8xLCB1bWFwXzIpLCBjZW50ZXJzID0gNCkNCg0KDQoNCg0KDQpjZF9maW5hbCAlPD4lIA0KICAgIG11dGF0ZShjbHVzdGVyID0gcGFzdGUwKCdjbHVzdGVyXycsIGNsdXN0ZXJzJGNsdXN0ZXIpKQ0KDQpjZF9maW5hbCAlPiUgDQogICAgcGxvdF9seSh4ID0gfiB1bWFwXzEsDQogICAgICAgICAgICB5ID0gfiB1bWFwXzIsIA0KICAgICAgICAgICAgY29sb3IgPSB+IGNsdXN0ZXIpICU+JSANCiAgICBhZGRfbWFya2Vycyhob3ZlcmluZm8gPSAndGV4dCcsDQogICAgICAgICAgICAgICAgdGV4dCA9IH4gbG9jYXRpb24sDQogICAgICAgICAgICAgICAgc3ltYm9sID0gfiBjb250aW5lbnQpDQoNCmNkX2ZpbmFsICU+JSANCiAgICBoY2hhcnQoJ3NjYXR0ZXInLA0KICAgICAgICAgICBoY2Flcyh4ID0gdW1hcF8xLA0KICAgICAgICAgICAgICAgICB5ID0gdW1hcF8yLA0KICAgICAgICAgICAgICAgICBncm91cCA9IGNvbnRpbmVudCwNCiAgICAgICAgICAgICAgICAgY29sb3IgPSBjbHVzdGVyLA0KICAgICAgICAgICAgICAgICBzaXplID0gcG9wdWxhdGlvbiAvIG1heChwb3B1bGF0aW9uKSksDQogICAgICAgICAgIHNob3dJbkxlZ2VuZCA9IEZBTFNFKSAlPiUgDQogICAgaGNfeUF4aXMoDQogICAgdGl0bGUgPSBsaXN0KHRleHQgPSAieSBBeGlzIGF0IHJpZ2h0IiksDQogICAgb3Bwb3NpdGUgPSBUUlVFLA0KICAgIGFsdGVybmF0ZUdyaWRDb2xvciA9ICIjRkFGQUZBIiwNCiAgICBtaW5vclRpY2tJbnRlcnZhbCA9ICJhdXRvIiwNCiAgICBtaW5vckdyaWRMaW5lRGFzaFN0eWxlID0gIkxvbmdEYXNoRG90RG90IiwNCiAgICBzaG93Rmlyc3RMYWJlbCA9IFRSVUUsDQogICAgc2hvd0xhc3RMYWJlbCA9IFRSVUUNCiAgICAgICkNCiAgICAgDQoNCg0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGlyaXMpICsNCiAgICBhZXMoU2VwYWwuTGVuZ3RoLCBTZXBhbC5XaWR0aCwgY29sb3IgPSBTcGVjaWVzKSArDQogICAgZ2VvbV9wb2ludCgpDQoNCmlyaXMgJT4lIA0KICAgIHBsb3RfbHkoeCA9IH4gU2VwYWwuTGVuZ3RoLCB5ID0gfiBTZXBhbC5XaWR0aCwgY29sb3IgPSB+IFNwZWNpZXMpICU+JSANCiAgICBhZGRfbWFya2VycygpDQpgYGANCg0KYGBge3J9DQpwYWNtYW46OnBfbG9hZChlY2hhcnRzNHIpDQplX2NvbW1vbihmb250X2ZhbWlseSA9ICJoZWx2ZXRpY2EiLCB0aGVtZSA9IE5VTEwpDQoNCg0KY2RfZmluYWwgJT4lIA0KICAgIHBsb3RfbHkoeCA9IH4gdW1hcF8xLA0KICAgICAgICAgICAgeSA9IH4gdW1hcF8yLCANCiAgICAgICAgICAgIGNvbG9yID0gfiBjbHVzdGVyKSAlPiUgDQogICAgYWRkX21hcmtlcnMoaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgICAgICAgICAgICAgIHRleHQgPSB+IGxvY2F0aW9uLA0KICAgICAgICAgICAgICAgIHN5bWJvbCA9IH4gY29udGluZW50KQ0KDQpjZF9maW5hbCAlPiUgDQogIGVfY2hhcnQodW1hcF8xKSAlPiUNCiAgZV9zY2F0dGVyKHVtYXBfMiwNCiAgICAgICAgICAgIG5hbWUgPSAnRGltZW50aW9uYWwgUmVkdWN0aW9uJykgJT4lIA0KICBlX2xtKHVtYXBfMiB+IHVtYXBfMSwgbmFtZSA9ICdsaW5lYXIgbW9kZWwnLA0KICAgICAgIGNvbmZpZyA9IGxpc3QoZm9ybXVsYU9uID0gJ2VuZCcsIG1ldGhvZCA9ICdsaW5lYXInKSkgJT4lIA0KICBlX2F4aXNfbGFiZWxzKHggPSAnVU1BUCAxJywgeSA9ICdVTUFQIDInKSAlPiUgDQogIGVfdGl0bGUodGV4dCA9ICdBbmFseXNpcyBvZiBEaW1lbnRpb25hbCBSZWR1Y3Rpb24nLA0KICAgICAgICAgIHN1YnRleHQgPSAnVU1BUCcpICU+JSANCiAgZV94X2F4aXMobmFtZUxvY2F0aW9uID0gJ2NlbnRlcicsDQogICAgICAgICAgIHNwbGl0QXJlYSA9IGxpc3Qoc2hvdyA9IEZBTFNFKSwNCiAgICAgICAgICAgYXhpc0xhYmVsID0gbGlzdChtYXJnaW4gPSAzKSwNCiAgICAgICAgICAgYXhpc1BvaW50ZXIgPSBsaXN0KA0KICAgICAgICAgICAgIHNob3cgPSBUUlVFLA0KICAgICAgICAgICAgIGxpbmVTdHlsZSA9IGxpc3QoDQogICAgICAgICAgICAgICBjb2xvciA9ICcjMDAwMDAwJywNCiAgICAgICAgICAgICAgIHdpZHRoID0gMC43NSwNCiAgICAgICAgICAgICAgIHR5cGUgPSAnZG90dGVkJw0KICAgICAgICAgICAgICkNCiAgICAgICAgICAgKSkgJT4lIA0KICBlX3lfYXhpcyhuYW1lTG9jYXRpb24gPSAnY2VudGVyJywNCiAgICAgICAgICAgc3BsaXRBcmVhID0gbGlzdChzaG93ID0gRkFMU0UpLA0KICAgICAgICAgICBheGlzTGFiZWwgPSBsaXN0KG1hcmdpbiA9IDMpLA0KICAgICAgICAgICBheGlzUG9pbnRlciA9IGxpc3QoDQogICAgICAgICAgICAgc2hvdyA9IFRSVUUsDQogICAgICAgICAgICAgbGluZVN0eWxlID0gbGlzdCgNCiAgICAgICAgICAgICAgIGNvbG9yID0gJyMwMDAwMDAnLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjc1LA0KICAgICAgICAgICAgICAgdHlwZSA9ICdkb3R0ZWQnDQogICAgICAgICAgICAgKQ0KICAgICAgICAgICApKSANCiAgI2VfdG9vbHRpcCgpDQpgYGANCg0KYGBge3J9DQpuX2JpbnMgPC0gMjUNCg0KY2RfZmluYWwgJT4lIA0KICBtdXRhdGUodW1hcF8xX2N1dCA9IGN1dCh1bWFwXzEsIG5fYmlucyksDQogICAgICAgICB1bWFwXzJfY3V0ID0gY3V0KHVtYXBfMiwgbl9iaW5zKSkgJT4lIA0KICBjb3VudCh1bWFwXzFfY3V0LCB1bWFwXzJfY3V0LCBjbHVzdGVyKSAlPiUNCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIA0KICBlX2NoYXJ0KHggPSB1bWFwXzFfY3V0KSAlPiUgDQogIGVfaGVhdG1hcCh1bWFwXzJfY3V0ICxuKSAlPiUgDQogIGVfdmlzdWFsX21hcChuKSAlPiUgDQogIGVfdGl0bGUoJ0hlYXQgbWFwJykNCmBgYA0KDQpgYGB7cn0NCnBhY21hbjo6cF9sb2FkKG55Y2ZsaWdodHMxMykNCmZsaWdodHMgPC0gbnljZmxpZ2h0czEzOjpmbGlnaHRzDQoNCmZsaWdodHMgJT4lIA0KICB0cmFuc211dGUod2VlayA9IGFzLkRhdGUoY3V0KHRpbWVfaG91ciwgIndlZWsiKSksIGRlcF9kZWxheSwgb3JpZ2luKSAlPiUgDQogIGdyb3VwX2J5KG9yaWdpbiwgd2VlaykgJT4lDQogIHN1bW1hcmlzZShkZXBfZGVsYXkgPSBzdW0oZGVwX2RlbGF5LCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGVfY2hhcnRzKHggPSB3ZWVrKSAlPiUgDQogIGVfZGF0YXpvb20odHlwZSA9ICdzbGlkZXInLA0KICAgICAgICAgICAgIHRvb2xib3ggPSBGQUxTRSwNCiAgICAgICAgICAgICBib3R0b20gPSAtNSkgJT4lDQogIGVfdG9vbHRpcCgpICU+JSANCiAgZV90aXRsZSgnRGVwYXJ0dXJlIGRlbGF5cyBieSBhaXJwb3J0JykgJT4lIA0KICBlX3hfYXhpcyh3ZWVrLCBheGlzUG9pbnRlciA9IGxpc3Qoc2hvdyA9IFRSVUUpKSAlPiUgDQogIGVfbGluZShkZXBfZGVsYXkpDQpgYGANCg0KYGBge3J9DQpteV9zY2FsZSA8LSBmdW5jdGlvbih4KXsNCiAgc2NhbGVzOjpyZXNjYWxlKHgsIHRvID0gYyg1LCAxNSkpDQp9DQoNCmlyaXMgJT4lIA0KICAgIGVfY2hhcnRzKFBldGFsLldpZHRoKSAlPiUgDQogICAgZV9zY2F0dGVyKFBldGFsLkxlbmd0aCwgU2VwYWwuV2lkdGgsIHNjYWxlID0gbXlfc2NhbGUpICU+JSANCiAgICBlX3hfYXhpcyhuYW1lTG9jYXRpb24gPSAnY2VudGVyJywNCiAgICAgICAgICAgc3BsaXRBcmVhID0gbGlzdChzaG93ID0gRkFMU0UpLA0KICAgICAgICAgICBheGlzTGFiZWwgPSBsaXN0KG1hcmdpbiA9IDMpLA0KICAgICAgICAgICBheGlzUG9pbnRlciA9IGxpc3QoDQogICAgICAgICAgICAgc2hvdyA9IFRSVUUsDQogICAgICAgICAgICAgbGluZVN0eWxlID0gbGlzdCgNCiAgICAgICAgICAgICAgIGNvbG9yID0gJyMwMDAwMDAnLA0KICAgICAgICAgICAgICAgd2lkdGggPSAwLjc1LA0KICAgICAgICAgICAgICAgdHlwZSA9ICdkb3R0ZWQnDQogICAgICAgICAgICAgKQ0KICAgICAgICAgICApKSAlPiUgDQogIGVfeV9heGlzKG5hbWVMb2NhdGlvbiA9ICdjZW50ZXInLA0KICAgICAgICAgICBzcGxpdEFyZWEgPSBsaXN0KHNob3cgPSBGQUxTRSksDQogICAgICAgICAgIGF4aXNMYWJlbCA9IGxpc3QobWFyZ2luID0gMyksDQogICAgICAgICAgIGF4aXNQb2ludGVyID0gbGlzdCgNCiAgICAgICAgICAgICBzaG93ID0gVFJVRSwNCiAgICAgICAgICAgICBsaW5lU3R5bGUgPSBsaXN0KA0KICAgICAgICAgICAgICAgY29sb3IgPSAnIzAwMDAwMCcsDQogICAgICAgICAgICAgICB3aWR0aCA9IDAuNzUsDQogICAgICAgICAgICAgICB0eXBlID0gJ2RvdHRlZCcNCiAgICAgICAgICAgICApDQogICAgICAgICAgICkpICU+JSANCiAgZV90b29sdGlwKCkNCmBgYA0KDQpgYGB7cn0NCmNvdmlkX2RhdGEgJT4lDQogIHNlbGVjdChkYXRlLCBsb2NhdGlvbiwgbmV3X2Nhc2VzKSAlPiUgDQogIGZpbHRlcihsb2NhdGlvbiA9PSAnQ2hpbGUnKSAlPiUNCiAgZmlsdGVyKGx1YnJpZGF0ZTo6eWVhcihkYXRlKSAlaW4lIGMoMjAyMCwgMjAyMSkpICU+JSANCiAgc2VsZWN0KC1sb2NhdGlvbikgJT4lIA0KICBlX2NoYXJ0cyhkYXRlKSAlPiUgDQogIGVfY2FsZW5kYXIocmFuZ2UgPSBjKCcyMDIwLTAzJywgJzIwMjEtMDQnKSkgJT4lIA0KICBlX2hlYXRtYXAobmV3X2Nhc2VzLCBjb29yZF9zeXN0ZW0gPSAnY2FsZW5kYXInKSAlPiUgDQogIGVfdmlzdWFsX21hcChtYXggPSBtYXgoODAwMCkpICU+JSANCiAgZV90b29sdGlwKCkNCmBgYA0KDQpgYGB7cn0NCmNvdmlkX2RhdGEgJT4lDQogIHNlbGVjdChkYXRlLCBsb2NhdGlvbiwgbmV3X2RlYXRocykgJT4lIA0KICBmaWx0ZXIobG9jYXRpb24gPT0gJ0NoaWxlJykgJT4lDQogIGZpbHRlcihsdWJyaWRhdGU6OnllYXIoZGF0ZSkgJWluJSBjKDIwMjAsIDIwMjEpKSAlPiUgDQogIHNlbGVjdCgtbG9jYXRpb24pICU+JSANCiAgZV9jaGFydHMoZGF0ZSkgJT4lIA0KICBlX2NhbGVuZGFyKHJhbmdlID0gYygnMjAyMC0wMycsICcyMDIxLTA0JyksIGRheUxhYmVsID0gbGlzdChmaXJzdERheSA9IDEpKSAlPiUgDQogIGVfaGVhdG1hcChuZXdfZGVhdGhzLCBjb29yZF9zeXN0ZW0gPSAnY2FsZW5kYXInKSAlPiUgDQogIGVfdmlzdWFsX21hcChtYXggPSBtYXgoMjAwKSwNCiAgICAgICAgICAgICAgIHRvcCA9ICdtaWRkbGUnKSAlPiUgDQogIGVfdG9vbHRpcCgpDQpgYGANCg0K